/*
 * 	Flan.Zeng 2011-2016	http://git.oschina.net/signup?inviter=flan
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.flan.stock.service;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.flan.stock.bean.Stock;
import com.flan.stock.net.StockDataSource;
import com.flan.stock.utils.Constant;
import com.flan.stock.utils.Log;

import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;

/**
 * 后台服务组件，用于处理远程获取股票数据等耗时操作
 * @author flan
 * @date   2015年12月24日
 */
public class StockService extends Service {
	
	private static final String tag = "StockService";
	private StockDataSource stockDataSource;
	private ServiceThread serviceThread;
	private static Map<Integer,UIListener> uiListenerMap = new HashMap<>();
	private Handler serviceHandler = new ServiceHandler(this);	//UI线程中的handler，不能用来更新UI
	private static Handler serviceThreadHandler;				//自定义线程（非UI线程）中的handler，不能用来更新UI

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
		
		//启动Socket通信线程
		stockDataSource = new StockDataSource("192.168.0.102",8888);
		//将UI线程中的handler出入
		stockDataSource.setServiceHandler(serviceHandler);
		stockDataSource.start();
		
		//启动后台服务器线程
		serviceThread = new ServiceThread();
		serviceThread.start();
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return super.onStartCommand(intent, flags, startId);
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		serviceThread.close();
		stockDataSource.close();
		uiListenerMap.clear();
	}
	
	/**
	 * 获取股票行情的排序数据
	 * @param start		数据起始ID
	 * @param wantnum	想要获取的记录数
	 * @param colunm	排序字段
	 * @param desc		0.升序 1.降序
	 * @param flag		异步请求中唯一标识某次请求的数字，发送时请求时传入，数据返回时原样传回
	 * @param listener	异步数据请求完成后的回调接口
	 */
	public static void getQuotationRank(int start,int wantnum,int colunm,int desc,int flag,UIListener listener){
		
		Message msg = Message.obtain();
		msg.what = Constant.SERVICE_QUOTATION_RANK_REQUEST;
		Bundle bundle = new Bundle();
		bundle.putInt("start", start);
		bundle.putInt("wantnum", wantnum);
		bundle.putInt("colunm", colunm);
		bundle.putInt("desc", desc);
		bundle.putInt("flag", flag);
		msg.setData(bundle);
		
		uiListenerMap.put(flag, listener);
		serviceThreadHandler.sendMessage(msg);
	}
	
	/**
	 * UI线程中的handler
	 * @author flan
	 * @date   2016年4月19日
	 */
	static class ServiceHandler extends Handler{
		
		private WeakReference<StockService> weakReference;

		public ServiceHandler(StockService stockService) {
			super();
			this.weakReference = new WeakReference<StockService>(stockService);
		}
		
		@Override
		public void handleMessage(Message msg) {
			
			//StockService service = weakReference.get();
			
			//获取股票涨跌排序数据
			if(msg.what == Constant.SERVICE_QUOTATION_RANK_REQUEST){
				
				Log.d(tag, "UI线程中的Handler执行,更新UI线程 flag："+msg.arg1);
				UIListener listener = uiListenerMap.get(msg.arg1);
				listener.refresh(msg.obj);
				
				//清除UIListener引用防止内存溢出
				uiListenerMap.remove(msg.what); 
				listener = null;
			}
		}
	}
	
	///////////////////////// 非UI线程中的操作   /////////////////////////
	
	/**
	 * 后台服务中的looper循环线程（非UI线程），可用于处理耗时操作
	 * @author flan
	 * @date   2015年12月25日
	 */
	class ServiceThread extends Thread{
		
		private Looper looper = null;
		
		public void close(){
			if(looper != null)
				looper.quit();
		}

		@Override
		public void run() {
			
			looper = Looper.myLooper();
			//使用looper建立消息循环的步骤
			//1、初始化looper
			Looper.prepare();
			//2.绑定handler到自定义线程中，并添加处理消息的方法；
			//那个线程要用来处理消息，就要把handler创建在改线程中
			serviceThreadHandler = new ServiceThreadHandler(StockService.this);
			//3.启动looper循环
			Looper.loop();
			
			Log.i(tag, "后台服务Lopper线程启动成功！");
		}
	}
	
	/**
	 * 自定义后台多线程中的handler
	 * @author flan
	 * @date   2015年12月25日
	 */
	static class ServiceThreadHandler extends Handler{
		
		private WeakReference<StockService> weakReference;
		
		public ServiceThreadHandler(StockService stockService) {
			super();
			this.weakReference = new WeakReference<StockService>(stockService);
		}
		
		@Override
		public void handleMessage(Message msg) {
			
			//在该方法中进行各种耗时的后台操作
			Log.d(tag, "耗时操作："+msg.what+" 开始进行...");
			StockService service = weakReference.get();
			
			//获取股票涨跌排序数据
			if(msg.what == Constant.SERVICE_QUOTATION_RANK_REQUEST){
				//NIO写操作，向远处服务器发送数据
				//System.out.println("NIO写操作，向远处服务器发送数据");
				service.stockDataSource.getStockRank(msg.getData());
			}
		}
	}
	
}















